/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ProOF.apl.problems.real;

import ProOF.apl.methods.GA.population.aPopulation;
import ProOF.apl.problems.real.functions.aRealFunction;
import ProOF.com.Communication;
import ProOF.com.LinkerNodes;
import ProOF.com.LinkerParameters;
import ProOF.com.LinkerResults;
import ProOF.com.LinkerValidations;
import ProOF.com.StreamProgress;
import ProOF.gen.best.nEvaluations;
import ProOF.gen.stopping.aStop;

/**
 *
 * @author hossomi
 */
public final class iStopStatistic extends aStop{
    public static final iStopStatistic obj = new iStopStatistic();
    
    private nEvaluations    eval;
    private StreamProgress  com;
    private aPopulation     pop;
    private aRealFunction   func;
    private double          confidence;
    private long            maxEval;
    
    @Override
    public String name() {
        return "Stop Statistically";
    }
    
    @Override
    public String description() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    
    @Override
    public void services(LinkerNodes win) throws Exception {
        eval = win.need(nEvaluations.class, eval);
        pop = win.need(aPopulation.class, pop);
        func = win.need(aRealFunction.class, func);
    }
    
    @Override
    public void parameters(LinkerParameters win) throws Exception {
        confidence = win.Dbl( "Stop Confidence", 0.95, 0.01, 1 );
    }
    
    @Override
    public void load() throws Exception {
        com = Communication.mkProgress("evaluation progress");
    }

    @Override
    public void start() throws Exception {
        super.start();
        double u = pop.getMutationRate();
        double a = confidence;
        int l = func.dimension();
        int n = pop.getSize();
        maxEval = (long) Math.ceil( Math.log(1 - a)/(n*Math.log(1 - Math.min(Math.pow(u,l), Math.pow(u-1,l)))));
    }
    
    @Override
    public boolean validation(LinkerValidations win) throws Exception {
        return true;
    }
    
    @Override
    public double progress() throws Exception {
        double p = eval.value()*1.0/maxEval;
        com.progress(p);
        return p;
    }  
    
    @Override
    public boolean end() throws Exception {
        progress();
        return eval.value() > maxEval;
    }

    @Override
    public void results(LinkerResults com) throws Exception {
        super.results(com);
        com.writeLong("Statistic eval max", maxEval);
    }
}
